home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1998 September
/
Macworld (1998-09).dmg
/
Shareware World
/
Info
/
For Developers
/
MacZoop 1.8.3
/
More Classes
/
Threads
/
ZThread.cp
< prev
next >
Wrap
Text File
|
1996-11-26
|
5KB
|
259 lines
/*************************************************************************************************
*
*
* ObjectMacZapp -- a standard Mac OOP application template
*
*
*
* ZThread.cpp -- an object that implements a single thread of execution
*
*
*
*
*
* © 1996, Graham Cox
*
*
*
*
*************************************************************************************************/
#include "ZThread.h"
#include "ZThreadedApplication.h"
// Constructor
ZThread::ZThread( long doPeriod, Size stackSize )
{
// Initialiase data members
fDone = FALSE;
itsID = kNoThreadID;
itsStack = stackSize;
itsPeriod = doPeriod;
}
// Destructor
ZThread::~ZThread()
{
// If the thread is running then kill it
if( itsID != kNoThreadID )
{
Terminate();
}
}
// ThreadEntry()
void ZThread::ThreadEntry()
{
while( !IsDone() )
{
// Call Do()
Do();
// and then sleep for itsPeriod ticks
SleepTicks( itsPeriod );
}
itsID = kNoThreadID;
}
// IsDone()
inline Boolean ZThread::IsDone()
{
return fDone;
}
// SetDoPeriod()
void ZThread::SetDoPeriod( long doPeriod )
{
itsPeriod = doPeriod;
}
// Start
void ZThread::Start()
{
// If we already have a thread but it's just stopped, call restart
if( itsID != kNoThreadID )
{
Restart();
}
else
{
// Get a new thread
FailOSErr( NewThread( kCooperativeThread,
(ThreadEntryProcPtr)(&ThreadEntryGlue),
this,
itsStack,
kCreateIfNeeded,
NULL,
&itsID ) );
// Install our custom context switchers...
// ... before we're switched in...
FailOSErr( SetThreadSwitcher( itsID, (ThreadSwitchProcPtr)(&SwitchingInGlue), this, TRUE ) );
// ... and before we're switched out
FailOSErr( SetThreadSwitcher( itsID, (ThreadSwitchProcPtr)(&SwitchingOutGlue), this, FALSE ) );
}
}
// Stop()
OSErr ZThread::Stop()
{
if( gMacHasThreadManager )
{
return SetThreadState( itsID, kStoppedThreadState, kNoThreadID );
}
else
{
return paramErr;
}
}
// Restart()
OSErr ZThread::Restart()
{
if( gMacHasThreadManager )
{
return SetThreadState( itsID, kReadyThreadState, kNoThreadID );
}
else
{
return paramErr;
}
}
// Terminate()
void ZThread::Terminate( Boolean fReturnToPool )
{
// Stop the thread
Stop();
if( gMacHasThreadManager )
{
// Dispose of it
DisposeThread( itsID, NULL, fReturnToPool );
}
// Set itsID so that we can't do anything else to this thread
itsID = kNoThreadID;
}
// GetState() returns current thread state in *pState
// The states are defined in Threads.h but can be a bit confusing.
//
// Basically my understanding is:
//
// - kReadyThreadState means that the thread is ready to run but is not the current
// thread. Normal running threads will return this if GetState() is called from
// another thread.
//
// - kStoppedThreadState means that the thread has been stopped by a Stop() instruction.
//
// - kRunningThreadState means that the thread is running *and* is the current thread.
// GetState() will return this if it's called from within Do() say.
//
ThreadState ZThread::GetState()
{
if( (itsID != kNoThreadID) && gMacHasThreadManager )
{
ThreadState state;
FailOSErr( GetThreadState( itsID, &state ) );
return state;
}
else
{
return kStoppedThreadState;
}
}
// SleepTicks()
void ZThread::SleepTicks( long ticksToSleep )
{
long lSleepTicks = TickCount() + ticksToSleep;
if( gMacHasThreadManager )
{
do {
YieldToAnyThread();
} while( TickCount() < lSleepTicks );
}
}
// Glue functions not part of ZThread
/******************************************************************************
ThreadEntryGlue
******************************************************************************/
pascal void * ThreadEntryGlue( ZThread* me )
{
// Trap exceptions - if an exception runs off the top of the
// thread stack we'll be in *real* trouble!
try
{
me->ThreadEntry();
}
catch(OSErr err)
{
}
return NULL;
}
/******************************************************************************
SwitchingInGlue
******************************************************************************/
pascal void SwitchingInGlue( ThreadID threadBeingSwitched, ZThread* me )
{
me->SwitchingIn();
}
/******************************************************************************
SwitchingOutGlue
******************************************************************************/
pascal void SwitchingOutGlue( ThreadID threadBeingSwitched, ZThread* me )
{
me->SwitchingOut();
}
// Utility function - yield for lTicks ticks
void YieldTicks( long lTicks )
{
if( gMacHasThreadManager )
{
long targetTicks = TickCount() + lTicks;
while( TickCount() < targetTicks )
{
YieldToAnyThread();
}
}
}
// Utility function - safe yield
void SafeYield()
{
if( gMacHasThreadManager )
YieldToAnyThread();
}